#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    Init();
    //开启串口线程
    comThread = new uartWork();
    comThread->startThread();
    uartIsOpen = false;

    //串口绑定信号槽
    connect(comThread, &uartWork::readyread, this, &MainWindow::readFromCom,
            Qt::QueuedConnection);
    connect(comThread, &uartWork::openError, this, &MainWindow::openSucess,
            Qt::QueuedConnection);
    connect(comThread, &uartWork::errOccurred, this, &MainWindow::errorOccurred,
            Qt::QueuedConnection);
    connect(this,&MainWindow::sendData2Uart, comThread, &uartWork::writeData,
            Qt::QueuedConnection);
    connect(this, &MainWindow::upCfg2Uart, comThread, &uartWork::updateComCfg,
            Qt::QueuedConnection);
    connect(this, &MainWindow::closeUart, comThread, &uartWork::stopThread,
            Qt::QueuedConnection);
    //创建解析对象
    m_analysis = new analysis_modbus();
    connect(this,&MainWindow::Start,m_analysis,&analysis_modbus::recvModbusMsg,
            Qt::QueuedConnection);
    connect(m_analysis,&analysis_modbus::analysis_over,this,&MainWindow::sendBackMsg,
            Qt::QueuedConnection);
    connect(m_analysis,&analysis_modbus::toUishowMsg,this,&MainWindow::ShowMsgString,
            Qt::QueuedConnection);
    connect(m_analysis,&analysis_modbus::toUishowMsgPack,this,&MainWindow::ShowMsgQByteArray,
            Qt::QueuedConnection);
    connect(m_analysis,&analysis_modbus::wirtTablec,this,&MainWindow::wirtTablec,
            Qt::QueuedConnection);
    connect(m_analysis,&analysis_modbus::wirtTabler,this,&MainWindow::wirtTabler,
            Qt::QueuedConnection);
}
void MainWindow::Init()
{
    qDebug()<<" UI主线程id=="<<QThread::currentThreadId();
    //读取串口信息
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        // 自动读取串口号添加到端口portBox中
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->ser_port_name->addItem(info.portName());
            serial.close();
        }
    }
    //显示当前时间
    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(timerShow()));
    m_timer->setInterval(1000);
    m_timer->start();
    //自动保存log
    m_logtimer = new QTimer(this);
    connect(m_logtimer, SIGNAL(timeout()), this, SLOT(WriteHistoricalMessage()));
    m_logtimer->setInterval(120000);
    m_logtimer->start();
    //表格初始化
    table_dataInit();
    readseting = new QSettings("dataini/Data.ini", QSettings::IniFormat);
    ReadOutIniData();
    m_msg_dialog = new msgDialog(this);
}
MainWindow::~MainWindow()
{
    delete ui;
    delete m_timer;
    delete m_logtimer;
    delete readseting;
    delete m_analysis;
}
//获取串口读取到的数据
void MainWindow::readFromCom(QByteArray disData)
{
    if (disData.isEmpty())
        return;
    uartSrcData = disData;
    m_addr = (quint8)ui->addr->text().toInt();
    emit Start(uartSrcData,m_addr);

    QString str;
    ByteToHexString(str,disData);
    ui->recv_Edit->append("收到报文:<---\r\n"+str+"\r\n");
    ui->recv_Edit->moveCursor(QTextCursor::End);
}
//发送回应报文
void MainWindow::sendBackMsg(QByteArray msg)
{
    emit sendData2Uart(msg);
}
//开启关闭串口
void MainWindow::on_ser_concent_clicked()
{
    // 打开串口
    if (uartIsOpen)
    {
        if(judgement("是否关闭串口？"))
        {
            ui->ser_concent->setText("打开串口");
            emit closeUart();
        }
    }
    else
    {
        res_config.portNum =ui->ser_port_name->currentText();
        res_config.baudRate =ui->bround_->currentText().toInt();
        res_config.dataBits =(QSerialPort::DataBits)(ui->data_bit->currentText().toInt());
        if(ui->check_code_bit->currentText()=="奇校验")
        {
            res_config.paritys =QSerialPort::OddParity;
        }
        else if(ui->check_code_bit->currentText()=="偶校验")
        {
            res_config.paritys =QSerialPort::EvenParity;
        }
        else if(ui->check_code_bit->currentText()=="无校验")
        {
            res_config.paritys =QSerialPort::NoParity;
        }
        res_config.stopBits =(QSerialPort::StopBits)(ui->stop_bit->currentText().toInt());

#if DEBUG

        qDebug() << "串口号：" << res_config.portNum <<endl;
        qDebug() << "波特率：" << res_config.baudRate <<endl;
        qDebug() << "校验：" << res_config.paritys <<endl;
        qDebug() << "停止位：" << res_config.stopBits <<endl;
        qDebug() << "数据位：" << res_config.dataBits <<endl;

#endif
        if(judgement("是否打开串口？"))
        {
            ui->ser_concent->setText("关闭串口");
            //发送信号开启串口
            emit upCfg2Uart(res_config);
        }
    }
}
//串口错误处理
void MainWindow::errorOccurred(QString error)
{
    if (false == error.isEmpty())
    {
        QMessageBox::information(this, "串口错误", error);
    }
}
//判断串口标志
void MainWindow::openSucess(bool sucess)
{
    if (sucess == true)
    {

        ui->ser_concent->setText("关闭串口");
        uartIsOpen = true;
        uartConfigDisTrue();

    } else
    {
        ui->ser_concent->setText("打开串口");
        uartIsOpen = false;
        uartConfigDisFalse();
    }
}
//刷新串口号
void MainWindow::on_pushButton_clicked()
{
    ui->ser_port_name->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {   //在portBox中显示可用串口
        ui->ser_port_name->addItem(info.portName());
    }
}
//打开串口后禁止配置参数
void MainWindow::uartConfigDisTrue()
{
    ui->ser_port_name->setDisabled(true);
    ui->stop_bit->setDisabled(true);
    ui->check_code_bit->setDisabled(true);
    ui->data_bit->setDisabled(true);
    ui->bround_->setDisabled(true);
}
//关闭串口后启动配置参数
void MainWindow::uartConfigDisFalse()
{
    ui->ser_port_name->setDisabled(false);
    ui->stop_bit->setDisabled(false);
    ui->check_code_bit->setDisabled(false);
    ui->data_bit->setDisabled(false);
    ui->bround_->setDisabled(false);
}
//显示异常信息
void MainWindow::ShowMsgString(QString error)
{
    ui->recv_Edit->append(error);
    ui->recv_Edit->moveCursor(QTextCursor::End);
}
//显示回应报文
void MainWindow::ShowMsgQByteArray(QByteArray ba)
{
    QString str;
    ByteToHexString(str,ba);
    ui->recv_Edit->append("回应报文\r\n"+str);
    ui->recv_Edit->moveCursor(QTextCursor::End);
}
//当前时间槽
void MainWindow::timerShow()
{
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");
    ui->time_line->setText(current_date);
}
//表格初始化
void MainWindow::table_dataInit()
{
    //设置表格
    QStringList TableHeader;
    TableHeader << "地址" << "数据";
    ui->table_coil->setVerticalHeaderLabels(TableHeader);
    ui->table_coil->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableregs->setVerticalHeaderLabels(TableHeader);
    ui->tableregs->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableregs->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->table_coil->setEditTriggers(QAbstractItemView::NoEditTriggers);
}
//将ini文件中的数据放到对应的表格中
void MainWindow::ReadOutIniData(void)
{
    for(int i = 0; i < (ADDRESS_MAX + 1); i++)
    {
        //地址设置
        QString adr =  "0x" + QString("%1").arg(i,4,16,QLatin1Char('0'));
        ui->table_coil->setItem(0,i, new QTableWidgetItem(QString(adr).toUpper()));
        ui->table_coil->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        ui->tableregs->setItem(0,i, new QTableWidgetItem(QString(adr)));
        ui->tableregs->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        //读出线圈数据
        QString coilData = readseting->value("Section" + QString::number(i+1) + "/coil").toString();
        //读出寄存器数据
        QString registerData = readseting->value("Section" + QString::number(i+1) + "/regi").toString();
        //在线圈数据表中显示数据
        ui->table_coil->setItem(1,i,new QTableWidgetItem(coilData));
        //设置表格内文字水平+垂直对齐
        ui->table_coil->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        //在寄存器数据表中显示数据
        ui->tableregs->setItem(1,i,new QTableWidgetItem(registerData));
        //设置表格内文字水平+垂直对齐
        ui->tableregs->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
}
//更新线圈表
void MainWindow::wirtTablec(quint16 num, quint16 satrtaddr,QString bac)
{
    ui->table_coil->blockSignals(true);
    for(int i = satrtaddr,k=0; k < num;k++,i++)
    {
        //在线圈数据表中显示数据
        QString data;
        if(bac[k] == '1')
        {
            data ="1";
        }
        else
        {
            data ="0";
        }
        ui->table_coil->setItem(1,i,new QTableWidgetItem(data));
        ui->table_coil->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
    ui->table_coil->blockSignals(false);
    bac.clear();
}
//更新寄存器表
void MainWindow::wirtTabler(quint16 num, quint16 satrtaddr,QVector<quint16> bar)
{
    ui->tableregs->blockSignals(true);
    for(int i = satrtaddr,k=0; k < num;k++,i++)
    {
        ui->tableregs->setItem(1,i,new QTableWidgetItem(QString("%1").arg(bar[k])));
        ui->tableregs->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
    ui->tableregs->blockSignals(false);
    bar.clear();
}
//切换tab表格
void MainWindow::on_tabWidget_tabBarClicked(int index)
{
    switch(index){

    case 0 :bar_indexs=0;
        break;
    case 1 :bar_indexs=1;
        break;
    default:
        break;
    }
}
//定位到线圈表指定位置
void MainWindow::ReadOutIniDatac(int start)
{
    QTableWidgetItem* item = ui->table_coil->item(0,start);
    ui->table_coil->setCurrentItem(item);
    ui->table_coil->scrollToItem(item,QAbstractItemView::PositionAtCenter);
}
//定位到寄存器表指定位置
void MainWindow::ReadOutIniDatar(int start)
{
    QTableWidgetItem* item = ui->tableregs->item(0,start);
    ui->tableregs->setCurrentItem(item);
    ui->tableregs->scrollToItem(item,QAbstractItemView::PositionAtCenter);
}
//写入通信记录到Txt文件内
void MainWindow::WriteHistoricalMessage()
{

    //消息框内显示清除的时间，和文件夹路径
    QFileInfo info(RECORD_PATH);
    //时间
    timerShow();
    //消息窗口显示信息
    ui->recv_Edit->append("保存至路径：" + info.filePath() + "\n文件名称：" + info.fileName()
                          + "\n文件大小：" + QString::number(info.size()) + "\n创建日期：" + info.created().toString("yyyy-MM-dd hh:mm:ss")
                          + "\n最后保存日期：" + info.lastModified().toString("yyyy-MM-dd hh:mm:ss") + "\n");

    //将历史记录写入文件，使用追加方式写入文件
    file = new QFile(RECORD_PATH);
    file->open(QFileDevice::Append);
    file->write(ui->recv_Edit->toPlainText().toUtf8().data());
    //消息分块
    file->write("\n\n");
    //清除消息框中的内容
    ui->recv_Edit->clear();
    file->close();
    delete file;
}
//起始地址和结束地址合法性检测
void MainWindow::on_check_clicked()
{
    int satrtaddr = ui->startaddr->text().toInt(NULL,10);
    if(bar_indexs==0)
    {
        if(satrtaddr>65535||satrtaddr<0)
        {
            QMessageBox::warning(this,"错误","起始地址超出范围，请重新输入!");
        }
        else
        {
            ReadOutIniDatac(satrtaddr);
        }
    }
    else if(bar_indexs==1)
    {
        if(satrtaddr>65535||satrtaddr<0)
        {
            QMessageBox::warning(this,"错误","起始地址超出范围，请重新输入!");
        }
        else
        {
            ReadOutIniDatar(satrtaddr);
        }
    }
}
//关闭程序事件
void MainWindow::closeEvent(QCloseEvent *event)
{

    QMessageBox::StandardButton close;
    close = QMessageBox::question(this,"提示","确认退出程序？",QMessageBox::Yes | QMessageBox::No,QMessageBox::No);

    if(close == QMessageBox::Yes)
    {
        //关闭界面，保存日志
        WriteHistoricalMessage();
        event->accept();
    }
    else
    {
        event->ignore();
    }
}
//从站地址限制
void MainWindow::on_addr_textChanged(const QString &arg1)
{
    int ad= arg1.toInt();
    if(ad>247||ad<1)
    {
        ui->addr->clear();
        QMessageBox::warning(this,"错误","从机地址1-247！");
    }
}
//清空窗口
void MainWindow::on_chear_clicked()
{
    if(judgement("是否清除窗口？"))
    {
      ui->recv_Edit->clear();
    }
}
//询问判断
bool MainWindow::judgement(QString msg)
{
    QMessageBox::StandardButton close;
    close = QMessageBox::question(this,"提示",msg,QMessageBox::Yes | QMessageBox::No,QMessageBox::No);

    if(close == QMessageBox::Yes)
    {
        return true;
    }
    else
    {
        return false;
    }
}
//查看历史记录
void MainWindow::on_check_2_clicked()
{
    wirteQStringtoTxt();
}
//读取历史文件信息
bool MainWindow::wirteQStringtoTxt()
{
    QString path = QFileDialog::getOpenFileName(this,"open","./","TXT(*.txt)");
    if(path.isEmpty() == false)
    {

        QMessageBox::information(this,"文件","选择路径成功！");
        //文件对象
        file = new QFile(path);
        //打开文件
        if(file->open(QIODevice::ReadWrite |QIODevice::Text)){
            QTextStream wstream(file);
            QString showmsg;
            showmsg = wstream.readAll();
            QMessageBox::information(this,"文件","打开成功！");
            file->close();
            delete file;
            m_msg_dialog->setMsg(showmsg.toLocal8Bit());
            m_msg_dialog->show();
            return true;
        }
        else
        {
            QMessageBox::information(this,"文件","打开失败！");
            delete file;
            return false;
        }
    }
    else
    {
        QMessageBox::information(this,"文件","选择路径失败！");
        delete file;
        return false;
    }
    return false;
}
